package tt.dz.util.Nosql.Redis.Connect;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.msgpack.MessagePack;
import org.msgpack.template.Templates;

import redis.clients.jedis.Jedis;
import tt.dz.util.Nosql.Jedis.Connect.JedisConnect;
import tt.dz.util.Nosql.Jedis.Const.JedisConst;
import tt.dz.util.Nosql.Redis.Model.ProductSubscribeInfo;
import tt.dz.util.Nosql.Redis.Template.RedisTemplate;

/**
 * redis数据库连接类
 * @author peizhide
 *
 */
public class RedisConnect {
	
	private static MessagePack messagePack = new MessagePack();

	private static final Log log = LogFactory.getLog(RedisConnect.class);
	
	/**
	 * 从redis中获取Object对象
	 * @author peizhide
	 * @param chargerId(包含两位枪口号)
	 * @param table 表名
	 * @param clazz pojo
	 * @return 成功:返回obj,失败:null
	 * @throws Exception
	 *
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static Object getObject(String chargerId, String table, Class clazz) {
		Object obj = null;
		try {
			byte[] redisResult = getRedisResult(chargerId, table);
			if (redisResult == null) {
				return null;
			}
			obj = messagePack.read(redisResult, clazz);
		} catch (Exception e) {
			e.printStackTrace();
			obj = null;
		}
		return obj;
	}
	
	/**
	 * 从redis中获取List对象
	 * @author peizhide
	 * @param chargerId(包含两位枪口号)
	 * @param table 表名
	 * @param clazz pojo
	 * @return 成功:有数据返回List对象,无数据返回null
	 * @throws Exception
	 *
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static List<Object> getRedisList(String chargerId, String table, Class clazz) {
		List<Object> result = null;
		try {
			byte[] hget = getRedisResult(chargerId, table);
			if (hget == null) {
				return null;
			}
			result = (ArrayList<Object>) messagePack.read(hget, Templates.tList(new RedisTemplate(clazz)));
		} catch (Exception e) {
			e.printStackTrace();
			result = null;
		}

		return result;
	}
	
	/**
	 * 从redis中获取Map对象
	 * @author peizhide
	 * @param chargerId(包含两位枪口号)
	 * @param table 表名
	 * @param clazz pojo
	 * @return 成功:map,失败:null
	 * @throws Exception
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static Map<Long, Object> getRedisMap(String chargerId, String table, Class clazz) {
		byte[] hget = null;
		try {
			hget = getRedisResult(chargerId, table);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		if (hget == null) {
			return null;
		}

		/**
		 * 将取得的字节数组反序列化成MAP,重写对象模板
		 */
		Map<Long, Object> resultMap = null;
		try {
			resultMap = (HashMap<Long, Object>) messagePack.read(hget,
					Templates.tMap(Templates.TLong, new RedisTemplate(clazz)));
		} catch (IOException e) {
			e.printStackTrace();
		}

		return resultMap;
	}
	
	/**
	 * 获取value(内部调用)
	 * @author peizhide
	 * @param chargerId(包含两位枪口号)
	 * @param table 表名
	 * @return byte[]
	 * @throws Exception
	 *
	 */
	private static byte[] getRedisResult(String chargerId, String table) throws Exception {
		Jedis jedis = JedisConnect.getConnect();
		byte[] hget = jedis.hget(chargerId.trim().getBytes(), messagePack.write(table.trim().toUpperCase()));
		JedisConnect.releaseConnect(jedis);
		return hget;
	}
	
	/**
	 * 存储Object到redis
	 * @author peizhide
	 * @param chargerId(包含两位枪口号)
	 * @param table 表名
	 * @param obj 当前入库对象
	 * @return 返回结果码(成功:0000,否则:失败)
	 * @throws Exception
	 *
	 */
	public static String setRedis(String chargerId, String table, Object obj) {
		String result = JedisConst.OPERATION_REDIS_RESULT_SUCCESS;
		try {
			Jedis jedis = JedisConnect.getConnect();
			jedis.hset(chargerId.trim().getBytes(), messagePack.write(table.trim().toUpperCase()),
					messagePack.write(obj));
			JedisConnect.releaseConnect(jedis);
		} catch (Exception e) {
			log.error("chargerId = " + chargerId + " table = " + table + " " + e.getMessage());
			result = JedisConst.OPERATION_REDIS_RESULT_ERROR;
		}
		return result;
	}
	
	/**
	 * 存储到redis,失败则回滚
	 * @author peizhide
	 * @param chargerId(包含两位枪口号)
	 * @param table 表名
	 * @param newobj 新对象
	 * @param oldObj 旧对象
	 * @return 返回结果码(成功:0000,否则:失败)
	 *
	 */
	public static String setRedisAndRollback(String chargerId, String table, Object newobj, Object oldObj) {
		String redis = setRedis(chargerId, table, newobj);
		if (!redis.endsWith(JedisConst.OPERATION_REDIS_RESULT_SUCCESS)) {
			setRedis(chargerId, table, oldObj);
		}
		return redis;
	}

	/**
	 * 从redis中删除对象
	 * @author peizhide
	 * @param chargerId(包含两位枪口号)
	 * @param table 表名
	 * @return 返回结果码(成功:0000,否则:失败)
	 * @throws Exception
	 *
	 */
	public static String deleteRedis(String chargerId, String table) {
		String result = JedisConst.OPERATION_REDIS_RESULT_SUCCESS;
		try {
			Jedis jedis = JedisConnect.getConnect();
			Long hdel = jedis.hdel(chargerId.getBytes(), messagePack.write(table.trim().toUpperCase()));
			if (hdel.intValue() != 1 && hdel.intValue() != 0) { // 操作成功
				result = JedisConst.OPERATION_REDIS_RESULT_ERROR;
			}
			JedisConnect.releaseConnect(jedis);
		} catch (Exception e) {
			e.printStackTrace();
			result = JedisConst.OPERATION_REDIS_RESULT_ERROR;
		}
		return result;
	}
	
	/**
	 * 从redis中删除Object对象,失败则回滚
	 * @author peizhide
	 * @param chargerId(包含两位枪口号)
	 * @param table 表名
	 * @param oldObj 旧对象
	 * @return 返回结果码(成功:0000,否则:失败)
	 *
	 */
	public static String deleRedisAndRollback(String chargerId, String table, Object oldObj) {
		String deleteRedis = deleteRedis(chargerId, table);
		if (!deleteRedis.endsWith(JedisConst.OPERATION_REDIS_RESULT_SUCCESS)) {
			setRedis(chargerId, table, oldObj);
		}
		return deleteRedis;
	}
	
	/**
	 * 从redis中删除list对象,失败则回滚
	 * @author peizhide
	 * @param chargerId(包含两位枪口号)
	 * @param table 表名
	 * @param newList 新对象
	 * @param oldList 旧对象
	 * @return 返回结果码(成功:0000,否则:失败)
	 */
	public static String deleRedisListAndRollback(String chargerId, String table, List<?> newList, List<?> oldList) {
		String deleteRedis = JedisConst.OPERATION_REDIS_RESULT_SUCCESS;;
		if (newList.size() <= 0) {
			deleteRedis = RedisConnect.deleRedisAndRollback(chargerId, table, oldList);
		} else {
			deleteRedis = RedisConnect.setRedisAndRollback(chargerId, table, newList, oldList);
		}
		return deleteRedis;
	}
	
	/**
	 * 更新redis and ssdb
	 * @author peizhide
	 * @param chargerId(包含两位枪口号)
	 * @param table
	 * @param newObj
	 * @param oldObj
	 * @param vars
	 * @param sql
	 * @throws Exception
	 *
	 */
	/*public static void updateRedisAndSsdb(String chargerId,String table, Object newObj, Object oldObj, List<SsdbVariable> vars,String sql) throws Exception{
		try {
			String result = RedisConnect.setRedis(chargerId, table, newObj);
			if(result.endsWith(JedisConst.OPERATION_REDIS_RESULT_SUCCESS)){
				int putData = SsdbConn.putData(chargerId, sql, vars);
				if(putData == -1){
					RedisConnect.setRedis(chargerId, table, oldObj);
				}
			}
		} catch (Exception e) {
			RedisConnect.setRedis(chargerId, table, oldObj);
			throw e;
		}
	}*/
	
	/**
	 * 新增redis和ssdb数据
	 * @author peizhide
	 * @param chargerId(包含两位枪口号)
	 * @param table
	 * @param obj
	 * @param sql
	 * @param vars
	 * @throws Exception
	 *
	 */
	/*public static void addRedisAndSsdb(String chargerId, String table, Object obj, String sql, List<SsdbVariable> vars) throws Exception{
		try {
			String result = RedisConnect.setRedis(chargerId, table, obj);
			if(result.endsWith(JedisConst.OPERATION_REDIS_RESULT_SUCCESS)){
				int putData = SsdbConn.putData(chargerId, sql, vars);
				if(putData == -1){
					RedisConnect.deleteRedis(chargerId, table);
				}
			}
		} catch (Exception e) {
			RedisConnect.deleteRedis(chargerId, table);
			throw e;
		}
	}*/
	
	public static void main(String[] args) {
		try {
			RedisConnect redisConnect = new RedisConnect();
			JedisConnect.init("192.168.5.209", 6379, 23, 11, 1, 1000, true, true);
			String chargerId = "4513111";
			handleObject(redisConnect, chargerId);
			
			chargerId = "4513222";
			handleList(redisConnect, chargerId);
			
			chargerId = "4513444";
			handleMap(redisConnect, chargerId);
			
			Jedis jedis = JedisConnect.getConnect();
			jedis.expire("4513444", 50);
		} catch (Exception e) {
			e.printStackTrace();
		}
		}
	
	/**
	 * 处理Object
	 */
	@SuppressWarnings("static-access")
	public static void handleObject(RedisConnect redisConnect, String chargerId) {
		// 1.插入
		ProductSubscribeInfo productSubscribeInfo_One = new ProductSubscribeInfo();
		
		String result = redisConnect.setRedis(chargerId,JedisConst.PRODUCT_SUBSCRIBE, productSubscribeInfo_One);
		
		
		if (result.endsWith(JedisConst.OPERATION_REDIS_RESULT_SUCCESS)) {
			System.out.println("handleObject insert success!");
		} else {
			System.out.println("handleObject insert fail!");
		}
		
		// 2.查询
		Object queryObj = new Object();
		queryObj = redisConnect.getObject(chargerId, JedisConst.PRODUCT_SUBSCRIBE, ProductSubscribeInfo.class);
		ProductSubscribeInfo queryTemp = (ProductSubscribeInfo) queryObj;
		System.out.println("handleObject queryTemp:"+queryTemp.toString());
		
		// 3.1更新 
		Object updateObj = new Object();
		updateObj = redisConnect.getObject(chargerId, JedisConst.PRODUCT_SUBSCRIBE, ProductSubscribeInfo.class);
		ProductSubscribeInfo updateTemp = (ProductSubscribeInfo) updateObj;
		updateTemp.setCountryCode("55");
		
		redisConnect.setRedisAndRollback(chargerId, JedisConst.PRODUCT_SUBSCRIBE, updateTemp, queryObj);
		
		// 3.2查询
		Object updateQueryObj = new Object();
		updateQueryObj = redisConnect.getObject(chargerId, JedisConst.PRODUCT_SUBSCRIBE, ProductSubscribeInfo.class);
		ProductSubscribeInfo queryQueryTemp = (ProductSubscribeInfo) updateQueryObj;
		System.out.println("handleObject queryQueryTemp:"+queryQueryTemp.toString());
		
		// 4.删除
		redisConnect.deleRedisAndRollback(chargerId, JedisConst.PRODUCT_SUBSCRIBE, updateObj);
	}
	
	/**
	 * 处理list
	 */
	@SuppressWarnings("static-access")
	public static void handleList(RedisConnect redisConnect, String chargerId) {
		// 1.插入
		List<ProductSubscribeInfo> productSubscribeInfoList = new ArrayList<ProductSubscribeInfo>();
		ProductSubscribeInfo productSubscribeInfo_One = new ProductSubscribeInfo();
		productSubscribeInfo_One.setCountryCode("11");
		productSubscribeInfo_One.setOperateType(12);
		productSubscribeInfoList.add(productSubscribeInfo_One);
		
		ProductSubscribeInfo productSubscribeInfo_Two = new ProductSubscribeInfo();
		productSubscribeInfo_Two.setCountryCode("21");
		productSubscribeInfo_Two.setOperateType(22);
		productSubscribeInfoList.add(productSubscribeInfo_Two);
		
		String result = redisConnect.setRedis(chargerId,JedisConst.PRODUCT_SUBSCRIBE, productSubscribeInfoList);
		
		if (result.endsWith(JedisConst.OPERATION_REDIS_RESULT_SUCCESS)) {
			System.out.println("handleList insert success!");
		} else {
			System.out.println("handleList insert fail!");
		}
		
		// 2.查询
		List<Object> queryList = new ArrayList<Object>();
		queryList = redisConnect.getRedisList(chargerId, JedisConst.PRODUCT_SUBSCRIBE, ProductSubscribeInfo.class);
		for (Object obj : queryList) {
			ProductSubscribeInfo temp = (ProductSubscribeInfo) obj;
			System.out.println("handleList query:" + temp.toString());
		}
		
		// 3.1更新
		List<Object> updateList = new ArrayList<Object>();
		updateList = redisConnect.getRedisList(chargerId, JedisConst.PRODUCT_SUBSCRIBE, ProductSubscribeInfo.class);
		for (Object obj : updateList) {
			ProductSubscribeInfo temp = (ProductSubscribeInfo) obj;
			if (temp.getCountryCode().equals("11")) { // 处理国家码
				temp.setOperateType(122);
			}
		}
		
		redisConnect.setRedisAndRollback(chargerId, JedisConst.PRODUCT_SUBSCRIBE, updateList, updateList);
		
		// 3.2查询
		List<Object> updateQueryList = new ArrayList<Object>();
		updateQueryList = redisConnect.getRedisList(chargerId, JedisConst.PRODUCT_SUBSCRIBE, ProductSubscribeInfo.class);
		for (Object obj : updateQueryList) {
			ProductSubscribeInfo temp = (ProductSubscribeInfo) obj;
			System.out.println("handleList updateQueryList:" + temp.toString());
		}
		
		// 4.删除
		redisConnect.deleRedisListAndRollback(chargerId, JedisConst.PRODUCT_SUBSCRIBE, updateList, new ArrayList<Object>());
	}
	
	/**
	 * 处理map
	 */
	@SuppressWarnings("static-access")
	public static void handleMap(RedisConnect redisConnect, String chargerId) {
		// 1.插入
		Map<Long, Object> map = new HashMap<Long, Object>();
		ProductSubscribeInfo productSubscribeInfo_One = new ProductSubscribeInfo();
		productSubscribeInfo_One.setCountryCode("11");
		productSubscribeInfo_One.setOperateType(12);
		map.put(1L, productSubscribeInfo_One);
		ProductSubscribeInfo productSubscribeInfo_Two = new ProductSubscribeInfo();
		productSubscribeInfo_Two.setCountryCode("21");
		productSubscribeInfo_Two.setOperateType(22);
		map.put(2L, productSubscribeInfo_Two);
		
		String result = redisConnect.setRedis(chargerId,JedisConst.PRODUCT_SUBSCRIBE, map);
		
		if (result.endsWith(JedisConst.OPERATION_REDIS_RESULT_SUCCESS)) {
			System.out.println("handleMap insert success!");
		} else {
			System.out.println("handleMap insert fail!");
		}
		
		// 2.查询
		Map<Long, Object> queryMap = new HashMap<Long, Object>();
		queryMap = redisConnect.getRedisMap(chargerId, JedisConst.PRODUCT_SUBSCRIBE, ProductSubscribeInfo.class);
		Iterator<Entry<Long, Object>> queryIterator = queryMap.entrySet().iterator();
		while (queryIterator.hasNext()) {
		   Entry<Long, Object> str = queryIterator.next();
		   System.out.println("handleMap query key = " + str.getKey() + "," + "handleMap query value = " + str.getValue());
		}	
		
		// 3.1更新 
		Map<Long, Object> updateMap = new HashMap<Long, Object>();
		updateMap = redisConnect.getRedisMap(chargerId, JedisConst.PRODUCT_SUBSCRIBE, ProductSubscribeInfo.class);
		Iterator<Entry<Long, Object>> updateIterator = updateMap.entrySet().iterator();
		while (updateIterator.hasNext()) {
		   Entry<Long, Object> str = updateIterator.next();
		   if (str.getKey() == 1) {
			   ProductSubscribeInfo productSubscribeInfo = (ProductSubscribeInfo) str.getValue();
			   productSubscribeInfo.setCountryCode("888");
		   }
		}
		
		redisConnect.setRedis(chargerId, JedisConst.PRODUCT_SUBSCRIBE, updateMap);
		
		// 3.2查询
		Map<Long, Object> updateQueryMap = new HashMap<Long, Object>();
		updateQueryMap = redisConnect.getRedisMap(chargerId, JedisConst.PRODUCT_SUBSCRIBE, ProductSubscribeInfo.class);
		Iterator<Entry<Long, Object>> updateQueryIterator = updateQueryMap.entrySet().iterator();
		while (updateQueryIterator.hasNext()) {
		   Entry<Long, Object> str = updateQueryIterator.next();
		   System.out.println("handleMap updateQueryIterator key = " + str.getKey() + "," + "handleMap updateQueryIterator value = " + str.getValue());
		}
		
		// 4.删除
		redisConnect.deleRedisAndRollback(chargerId, JedisConst.PRODUCT_SUBSCRIBE, updateQueryMap);
	}
}
